home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 076-100 / 085 / csh / sub.c < prev   
C/C++ Source or Header  |  1995-03-13  |  13KB  |  612 lines

  1.  
  2. /*
  3.  * SUB.C
  4.  *
  5.  * (c)1986 Matthew Dillon     9 October 1986
  6.  *
  7.  * version 2.06M (Manx Version and Additions) by Steve Drew 28-May-87
  8.  *
  9.  */
  10.  
  11. #include "shell.h"
  12.  
  13. #define HM_STR 0          /* various HISTORY retrieval modes */
  14. #define HM_REL 1
  15. #define HM_ABS 2
  16.  
  17. /* extern struct FileLock *Clock; */
  18. seterr()
  19. {
  20.    char buf[32];
  21.    int stat;
  22.  
  23.    sprintf(buf, "%d", Lastresult);
  24.    set_var(LEVEL_SET, V_LASTERR, buf);
  25.    stat = atoi(get_var(LEVEL_SET, V_STAT));
  26.    if (stat < Lastresult)
  27.       stat = Lastresult;
  28.    sprintf(buf, "%d", stat);
  29.    set_var(LEVEL_SET, V_STAT, buf);
  30. }
  31.  
  32.  
  33. char *
  34. next_word(str)
  35. register char *str;
  36. {
  37.    while (*str    &&  *str != ' '     &&  *str != 9)
  38.       ++str;
  39.    while (*str    && (*str == ' ' || *str == 9))
  40.       ++str;
  41.    return (str);
  42. }
  43.  
  44.  
  45. char *
  46. compile_av(av, start, end)
  47. char **av;
  48. {
  49.    char *cstr;
  50.    int i, len;
  51.  
  52.    len = 0;
  53.    for (i = start; i < end; ++i)
  54.       len += strlen(av[i]) + 1;
  55.    cstr = malloc(len + 1);
  56.    *cstr = '\0';
  57.    for (i = start; i < end; ++i) {
  58.       strcat (cstr, av[i]);
  59.       strcat (cstr, " ");
  60.    }
  61.    return (cstr);
  62. }
  63.  
  64. /*
  65.  * FREE(ptr)   --frees without actually freeing, so the data is still good
  66.  *         immediately after the free.
  67.  */
  68.  
  69.  
  70. Free(ptr)
  71. char *ptr;
  72. {
  73.    static char *old_ptr;
  74.  
  75.    if (old_ptr)
  76.       free (old_ptr);
  77.    old_ptr = ptr;
  78. }
  79.  
  80. /*
  81.  * Add new string to history (H_head, H_tail, H_len,
  82.  *  S_histlen
  83.  */
  84.  
  85. add_history(str)
  86. char *str;
  87. {
  88.    register struct HIST *hist;
  89.  
  90.    if (H_head != NULL && strcmp(H_head->line, str) == 0)
  91.        return(0);
  92.    while (H_len > S_histlen)
  93.       del_history();
  94.    hist = (struct HIST *)malloc (sizeof(struct HIST));
  95.    if (H_head == NULL) {
  96.       H_head = H_tail = hist;
  97.       hist->next = NULL;
  98.    } else {
  99.       hist->next = H_head;
  100.       H_head->prev = hist;
  101.       H_head = hist;
  102.    }
  103.    hist->prev = NULL;
  104.    hist->line = malloc (strlen(str) + 1);
  105.    strcpy (hist->line, str);
  106.    ++H_len;
  107. }
  108.  
  109. del_history()
  110. {
  111.    if (H_tail) {
  112.       --H_len;
  113.       ++H_tail_base;
  114.       free (H_tail->line);
  115.       if (H_tail->prev) {
  116.      H_tail = H_tail->prev;
  117.      free (H_tail->next);
  118.      H_tail->next = NULL;
  119.       } else {
  120.      free (H_tail);
  121.      H_tail = H_head = NULL;
  122.       }
  123.    }
  124. }
  125.  
  126. char *
  127. get_history(ptr)
  128. char *ptr;
  129. {
  130.    register struct HIST *hist;
  131.    register int len;
  132.    int mode = HM_REL;
  133.    int num  = 1;
  134.    char *str;
  135.    char *result = NULL;
  136.  
  137.    if (ptr[1] >= '0' && ptr[1] <= '9') {
  138.       mode = HM_ABS;
  139.       num  = atoi(&ptr[1]);
  140.       goto skip;
  141.    }
  142.    switch (ptr[1]) {
  143.    case '!':
  144.       break;
  145.    case '-':
  146.       num += atoi(&ptr[2]);
  147.       break;
  148.    default:
  149.       mode = HM_STR;
  150.       str  = ptr + 1;
  151.       break;
  152.    }
  153. skip:
  154.    switch (mode) {
  155.    case HM_STR:
  156.       len = strlen(str);
  157.       for (hist = H_head; hist; hist = hist->next) {
  158.      if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
  159.         result = hist->line;
  160.         break;
  161.      }
  162.       }
  163.       break;
  164.    case HM_REL:
  165.       for (hist = H_head; hist && num--; hist = hist->next);
  166.       if (hist)
  167.      result = hist->line;
  168.       break;
  169.    case HM_ABS:
  170.       len = H_tail_base;
  171.       for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  172.       if (hist)
  173.      result = hist->line;
  174.       break;
  175.    }
  176.    if (result) {
  177.       fprintf(stderr,"%s\n",result);
  178.       return(result);
  179.    }
  180.    printf("History failed\n");
  181.    return ("");
  182. }
  183.  
  184. replace_head(str)
  185. char *str;
  186. {
  187.    if (str == NULL)
  188.       str = "";
  189.    if (H_head) {
  190.       free (H_head->line);
  191.       H_head->line = malloc (strlen(str)+1);
  192.       strcpy (H_head->line, str);
  193.    }
  194. }
  195.  
  196.  
  197. pError(str)
  198. char *str;
  199. {
  200.    int ierr = (long)IoErr();
  201.    ierror(str, ierr);
  202. }
  203.  
  204. ierror(str, err)
  205. register char *str;
  206. {
  207.    register struct PERROR *per = Perror;
  208.  
  209.    if (err) {
  210.       for (; per->errstr; ++per) {
  211.      if (per->errnum == err) {
  212.         fprintf (stderr, "%s%s%s\n",
  213.           per->errstr,
  214.           (str) ? ": " : "",
  215.           (str) ? str : "");
  216.         return ((short)err);
  217.      }
  218.       }
  219.       fprintf (stderr, "Unknown DOS error %ld %s\n", err, (str) ? str : "");
  220.    }
  221.    return ((short)err);
  222. }
  223.  
  224. /*
  225.  * Disk directory routines
  226.  *
  227.  * dptr = dopen(name, stat)
  228.  *    struct DPTR *dptr;
  229.  *    char *name;
  230.  *    int *stat;
  231.  *
  232.  * dnext(dptr, name, stat)
  233.  *    struct DPTR *dptr;
  234.  *    char **name;
  235.  *    int  *stat;
  236.  *
  237.  * dclose(dptr)             -may be called with NULL without harm
  238.  *
  239.  * dopen() returns a struct DPTR, or NULL if the given file does not
  240.  * exist.  stat will be set to 1 if the file is a directory.  If the
  241.  * name is "", then the current directory is openned.
  242.  *
  243.  * dnext() returns 1 until there are no more entries.  The **name and
  244.  * *stat are set.  *stat = 1 if the file is a directory.
  245.  *
  246.  * dclose() closes a directory channel.
  247.  *
  248.  */
  249.  
  250. struct DPTR *
  251. dopen(name, stat)
  252. char *name;
  253. int *stat;
  254. {
  255.    struct DPTR *dp;
  256.  
  257.    *stat = 0;
  258.    dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  259.    if (*name == '\0')
  260.       dp->lock = (struct FileLock *)DupLock ((struct FileLock *)Myprocess->pr_CurrentDir);
  261.    else
  262.       dp->lock = (struct FileLock *)Lock (name, ACCESS_READ);
  263.    if (dp->lock == NULL) {
  264.       free (dp);
  265.       return (NULL);
  266.    }
  267.    dp->fib = (struct FileInfoBlock *)
  268.      AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
  269.    if (!Examine (dp->lock, dp->fib)) {
  270.       pError (name);
  271.       dclose (dp);
  272.       return (NULL);
  273.    }
  274.    if (dp->fib->fib_DirEntryType >= 0)
  275.       *stat = 1;
  276.    return (dp);
  277. }
  278.  
  279. dnext(dp, pname, stat)
  280. struct DPTR *dp;
  281. char **pname;
  282. int *stat;
  283. {
  284.    if (dp == NULL)
  285.       return (0);
  286.    if (ExNext (dp->lock, dp->fib)) {
  287.       *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  288.       *pname = dp->fib->fib_FileName;
  289.       return (1);
  290.    }
  291.    return (0);
  292. }
  293.  
  294.  
  295. dclose(dp)
  296. struct DPTR *dp;
  297. {
  298.    if (dp == NULL)
  299.       return (1);
  300.    if (dp->fib)
  301.       FreeMem (dp->fib,(long)sizeof(*dp->fib));
  302.    if (dp->lock)
  303.       UnLock (dp->lock);
  304.    free (dp);
  305.    return (1);
  306. }
  307.  
  308.  
  309. isdir(file)
  310. char *file;
  311. {
  312.    register struct DPTR *dp;
  313.    int stat;
  314.  
  315.    stat = 0;
  316.    if (dp = dopen (file, &stat))
  317.       dclose(dp);
  318.    return (stat == 1);
  319. }
  320.  
  321.  
  322. free_expand(av)
  323. register char **av;
  324. {
  325.    char **base = av;
  326.  
  327.    if (av) {
  328.       while (*av) {
  329.      free (*av);
  330.      ++av;
  331.       }
  332.       free (base);
  333.    }
  334. }
  335.  
  336. /*
  337.  * EXPAND(base,pac)
  338.  *    base         - char * (example: "df0:*.c")
  339.  *    pac         - int  *  will be set to # of arguments.
  340.  *
  341.  * 22-May-87 SJD.  Heavily modified to allow recursive wild carding and
  342.  *           simple directory/file lookups. Returns a pointer to
  343.  *           an array of pointers that contains the full file spec
  344.  *           eg. 'df0:c/sear*' would result in : 'df0:C/Search'
  345.  *
  346.  *           Now no longer necessary to Examine the files a second time
  347.  *           in do_dir since expand will return the full file info
  348.  *           appended to the file name. Set by formatfile().
  349.  *           eg. fullfilename'\0'rwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS
  350.  *
  351.  *           Caller must call free_expand when done with the array.
  352.  *
  353.  * base            bname =      ename =
  354.  * ------        -------      -------
  355.  *  "*"              ""        "*"
  356.  *  "!*.info"          ""        "*.info" (wild_exclude set)
  357.  *  "su*d/*"          ""        "*"         (tail set)
  358.  *  "file.*"          ""        "file.*"
  359.  *  "df0:c/*"          "df0:c"        "*"
  360.  *  ""              ""        "*"
  361.  *  "df0:.../*"          "df0:"        "*"         (recur set)
  362.  *  "df0:sub/.../*"   "df0:sub"        "*"         (recur set)
  363.  *
  364.  * ---the above base would be provided by execom.c or do_dir().
  365.  * ---the below base would only be called from do_dir().
  366.  *
  367.  *  "file.c"          "file.c"        ""         if (dp == 0) fail else get file.c
  368.  *  "df0:"          "df0:"        "*"
  369.  *  "file/file"          "file/file"   ""         (dp == 0) so fail
  370.  *  "df0:.../"          "df0:"        "*"         (recur set)
  371.  *
  372.  */
  373.  
  374.  
  375. char **
  376. expand(base, pac)
  377. char *base;
  378. int *pac;
  379. {
  380.    register char *ptr;
  381.    char **eav = (char **)malloc(sizeof(char *) * (2));
  382.    short eleft, eac;
  383.    char *name;
  384.    char *svfile();
  385.    char *bname, *ename, *tail;
  386.    int stat, recur, scr,wild_exclude,bl;
  387.    register struct DPTR *dp;
  388.  
  389.    *pac = recur = eleft = eac = wild_exclude = 0;
  390.  
  391.    base = strcpy(malloc(strlen(base)+1), base);
  392.    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  393.  
  394.    if (!*ptr)    /* no wild cards */
  395.       --ptr;
  396.    else
  397.       for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  398.  
  399.    if (ptr < base) {
  400.       bname = strcpy (malloc(1), "");
  401.    } else {
  402.       scr = ptr[1];
  403.       ptr[1] = '\0';
  404.       if (!strcmp(ptr-3,".../")) {
  405.      recur = 1;
  406.      *(ptr-3) = '\0';
  407.       }
  408.       bname = strcpy (malloc(strlen(base)+2), base);
  409.       ptr[1] = scr;
  410.    }
  411.    bl = strlen(bname);
  412.    ename = ++ptr;
  413.    for (; *ptr && *ptr != '/'; ++ptr);
  414.    scr = *ptr;
  415.    *ptr = '\0';
  416.    if (scr) ++ptr;
  417.    tail = ptr;
  418.    if (*ename == '!') wild_exclude = 1;
  419.  
  420.    if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
  421.       free (bname);
  422.       free (base);
  423.       free (eav);
  424.       return (NULL);
  425.    }
  426.  
  427.    if (!stat) {               /* eg. 'dir file' */
  428.       char *p,*s;
  429.       for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
  430.       if (s != bname) ++s;
  431.       *s ='\0';
  432.       eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
  433.       goto done;
  434.    }
  435.    if (!*ename) ename = "*";    /* eg. dir df0: */
  436.    if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
  437.       bname[bl] = '/';
  438.       bname[++bl] = '\0';
  439.    }
  440.    while ((dnext (dp, &name, &stat)) && !breakcheck()) {
  441.     int match = compare_ok(ename+wild_exclude,name);
  442.  
  443.       if (wild_exclude) match ^= 1;
  444.       if (match && !(!recur && *tail)) {
  445.      if (eleft < 2) {
  446.            char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  447.            movmem (eav, scrav, (eac + 1) << 2);
  448.            free (eav);
  449.            eav = scrav;
  450.            eleft = 10;
  451.      }
  452.      eav[eac++] = svfile(bname,name,dp->fib);
  453.      --eleft;
  454.       }
  455.       if ((*tail && match) || recur) {
  456.      int alt_ac;
  457.      char *search, **alt_av, **scrav;
  458.      struct FileLock *lock;
  459.  
  460.      if (!stat)          /* expect more dirs, but this not a dir */
  461.         continue;
  462.      lock = (struct FileLock *)CurrentDir (dp->lock);
  463.      search = malloc(strlen(ename)+strlen(name)+strlen(tail)+5);
  464.      strcpy (search, name);
  465.      strcat (search, "/");
  466.      if (recur) {
  467.         strcat(search, ".../");
  468.         strcat(search, ename);
  469.      }
  470.      strcat (search, tail);
  471.      scrav = alt_av = expand (search, &alt_ac);
  472.      /* free(search); */
  473.      CurrentDir (lock);
  474.      if (scrav) {
  475.         while (*scrav) {
  476.            int l;
  477.            if (eleft < 2) {
  478.           char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  479.           movmem (eav, scrav, (eac + 1) << 2);
  480.           free (eav);
  481.           eav = scrav;
  482.           eleft = 10;
  483.            }
  484.  
  485.            l = strlen(*scrav);
  486.            scrav[0][l] = ' ';
  487.            eav[eac] = malloc(bl+l+40);
  488.            strcpy(eav[eac], bname);
  489.            strcat(eav[eac], *scrav);
  490.            eav[eac][l+bl] = '\0';
  491.  
  492.            free (*scrav);
  493.            ++scrav;
  494.            --eleft, ++eac;
  495.         }
  496.         free (alt_av);
  497.      }
  498.       }
  499.    }
  500. done:
  501.    dclose (dp);
  502.    *pac = eac;
  503.    eav[eac] = NULL;
  504.    free (bname);
  505.    free (base);
  506.    if (eac) {
  507.       return (eav);
  508.    }
  509.    free (eav);
  510.    return (NULL);
  511. }
  512.  
  513. /*
  514.  * Compare a wild card name with a normal name
  515.  */
  516.  
  517. #define MAXB   8
  518.  
  519. compare_ok(wild, name)
  520. char *wild, *name;
  521. {
  522.    register char *w = wild;
  523.    register char *n = name;
  524.    char *back[MAXB][2];
  525.    register char s1, s2;
  526.    int    bi = 0;
  527.  
  528.    while (*n || *w) {
  529.       switch (*w) {
  530.       case '*':
  531.      if (bi == MAXB) {
  532.         printf(stderr,"Too many levels of '*'\n");
  533.         return (0);
  534.      }
  535.      back[bi][0] = w;
  536.      back[bi][1] = n;
  537.      ++bi;
  538.      ++w;
  539.      continue;
  540. goback:
  541.      --bi;
  542.      while (bi >= 0 && *back[bi][1] == '\0')
  543.         --bi;
  544.      if (bi < 0)
  545.         return (0);
  546.      w = back[bi][0] + 1;
  547.      n = ++back[bi][1];
  548.      ++bi;
  549.      continue;
  550.       case '?':
  551.      if (!*n) {
  552.         if (bi)
  553.            goto goback;
  554.         return (0);
  555.      }
  556.      break;
  557.       default:
  558.      s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
  559.      s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
  560.      if (s1 != s2) {
  561.         if (bi)
  562.            goto goback;
  563.         return (0);
  564.      }
  565.      break;
  566.       }
  567.       if (*n)  ++n;
  568.       if (*w)  ++w;
  569.    }
  570.    return (1);
  571. }
  572.  
  573.  
  574. char *
  575. svfile(s1,s2,fib)
  576. char *s1,*s2;
  577. struct FileInfoBlock *fib;
  578. {
  579.    char *p;
  580.    p = malloc (strlen(s1)+strlen(s2)+40);
  581.    strcpy(p, s1);
  582.    strcat(p, s2);
  583.    formatfile(p,fib);
  584.    return(p);
  585. }
  586.  
  587. /* will have either of these formats:
  588.  *
  589.  *    fullfilename'\0'rwed    <Dir>     DD-MMM-YY HH:MM:SS\n'\0'
  590.  *    fullfilename'\0'rwed  NNNNNN NNNN     DD-MMM-YY HH:MM:SS\n'\0'
  591.  *              0123456789012345678901234567890123456 7  8
  592.  *
  593.  */
  594. formatfile(str,fib)
  595. char *str;
  596. register struct FileInfoBlock *fib;
  597. {
  598.    char *dates();
  599.  
  600.    while(*str++);
  601.    *str++ = (fib->fib_Protection & FIBF_READ)     ? '-' : 'r';
  602.    *str++ = (fib->fib_Protection & FIBF_WRITE)     ? '-' : 'w';
  603.    *str++ = (fib->fib_Protection & FIBF_EXECUTE) ? '-' : 'e';
  604.    *str++ = (fib->fib_Protection & FIBF_DELETE)     ? '-' : 'd';
  605.  
  606.    if (fib->fib_DirEntryType < 0)
  607.       sprintf(str,"  %6ld %4ld  ", (long)fib->fib_Size, (long)fib->fib_NumBlocks);
  608.    else
  609.       strcpy(str,"    <Dir>      ");
  610.    strcat(str,dates(&fib->fib_Date));
  611. }
  612.